package com.fzj.example.socket.tcp.block;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * TCP的服务器端：
 * 1.TCP的服务器端要创建ServerSocket对象，可以通过ServerSocket对象设置超时连接等；
 * 2.创建Socket对象，通过Socket对象和客户端进行通信；
 * 3.数据的输入输出和客户端是一样的，利用OutputStream、IntputStream、DataOutputStream、DataInputStream实现；
 * 4.利用线程实现；
 * @author fzj
 */
public class TcpServer{

    private static final int PORT = 9000;
    private static ServerSocket serverSocket;
    private static int count=0;
    /**
     * 在构造函数中创建ServerSocket对象；
     *  @parameter port:端口号
     *  @throws IOException
     */
    public TcpServer(int port)throws IOException {
        //创建连接
        //抛出异常：IOException
        serverSocket=new ServerSocket(port);
        //设定连接超时
        serverSocket.setSoTimeout(1000000);
    }

    /**
     * 线程的run函数
     */
    public void run(){
        /**
         * 创建Socket对象，通过Socket对象和客户端进行通信；
         * 数据的输入输出和客户端是一样的，利用OutputStream、
         * IntputStream、DataOutputStream、DataInputStream实现；
         */
        Socket socket = null;
        try {
            while(true) {
                System.out.println("等待客户端的连接，端口号为：" + serverSocket.getLocalPort());
                //创建Socket对象，并绑定server,这里会阻塞，如果想不阻塞，方案很简单，拿到socket，马上构建子线程处理
                socket=serverSocket.accept();
                //要做非阻塞，socket后面的逻辑都是异步的
                System.out.println("远程客户端主机地址为：" + socket.getRemoteSocketAddress());
                Thread.sleep(3000);
                //创建输入流，读取客户端传过来的数据
                InputStream inputFromClient=socket.getInputStream();
                DataInputStream in=new DataInputStream(inputFromClient);
                System.out.println("接收到的来自客户端[" + count++ + "]的信息为：" + in.readUTF());

                //创建输出流，对客户端做出回复
                OutputStream outputFromServer=socket.getOutputStream();
                DataOutputStream out=new DataOutputStream(outputFromServer);
                out.writeUTF("服务器的响应：谢谢连接。" + serverSocket.getLocalPort());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                serverSocket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        int port=9000;

        Runnable thread =()->{
            try {
                new TcpServer(port).run();
            } catch (IOException e) {
                e.printStackTrace();
            }
        };

        ExecutorService executorService=Executors.newCachedThreadPool();
        executorService.execute(thread);

    }

}
